package com.naiterui.ehp.bs.cms.modules.agent.service.impl;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.naiterui.ehp.bs.cms.common.utils.ReportUtil;
import com.naiterui.ehp.bs.cms.common.vo.PageParamsVO;
import com.naiterui.ehp.bs.cms.common.vo.PageVO;
import com.naiterui.ehp.bs.cms.modules.agent.entity.AgAgentArea;
import com.naiterui.ehp.bs.cms.modules.agent.mapper.AgAgentAreaMapper;
import com.naiterui.ehp.bs.cms.modules.agent.mapper.AgAgentMapper;
import com.naiterui.ehp.bs.cms.modules.agent.mapper.AgAreaMapper;
import com.naiterui.ehp.bs.cms.modules.agent.mapper.AsAreaCountMapper;
import com.naiterui.ehp.bs.cms.modules.agent.po.AreaPagePO;
import com.naiterui.ehp.bs.cms.modules.agent.service.IAgentAreaService;
import com.naiterui.ehp.bs.cms.modules.agent.service.IBusinessReportService;
import com.naiterui.ehp.bs.cms.modules.agent.vo.AreaExcelVO;
import com.naiterui.ehp.bs.cms.modules.agent.vo.AreaItemVO;
import com.naiterui.ehp.bs.cms.modules.agent.vo.AreaStatisticsDetailVO;
import com.naiterui.ehp.bs.cms.modules.agent.vo.AreaStatisticsReportVO;
import com.naiterui.ehp.bs.cms.modules.agent.vo.AreaStatisticsVO;
import com.naiterui.ehp.bs.cms.modules.agent.vo.AreaVO;
import com.naiterui.ehp.bs.cms.modules.agent.vo.BusinessStatisticsVO;
import com.naiterui.ehp.bs.cms.modules.agent.vo.ChildCityListVO;
import com.naiterui.ehp.bs.cms.modules.agent.vo.IdAndName;
import com.naiterui.ehp.bs.cms.modules.statistics.mapper.AsRecipelCountMapper;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author yangfuya
 * @since 2022/2/21
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BusinessReportServiceImpl implements IBusinessReportService {
    private final AsRecipelCountMapper asRecipelCountMapper;
    private final IAgentAreaService agentAreaService;
    private final AgAgentMapper agAgentMapper;
    private final AgAreaMapper agAreaMapper;
    private final AgAgentAreaMapper agAgentAreaMapper;
    private final AsAreaCountMapper asAreaCountMapper;

    @Override
    public BusinessStatisticsVO getStatistics(Long areaId) {
        BusinessStatisticsVO statisticsVO = new BusinessStatisticsVO();
        BusinessStatisticsVO allRecipelTotal = asRecipelCountMapper.getAllRecipelTotal();
        if (allRecipelTotal == null) {
            statisticsVO.setRecipelTotal(0);
            statisticsVO.setOrderTotal(0);
            statisticsVO.setOrderPriceTotal(0);
        } else {
            statisticsVO.setRecipelTotal(allRecipelTotal.getRecipelTotal());
            statisticsVO.setOrderTotal(allRecipelTotal.getOrderTotal());
            statisticsVO.setOrderPriceTotal(allRecipelTotal.getOrderPriceTotal());
        }
        Integer allInviteTotal = asRecipelCountMapper.getAllInviteTotal();
        if (allInviteTotal == null) {
            statisticsVO.setInviteTotal(0);
        } else {
            statisticsVO.setInviteTotal(allInviteTotal);
        }
        BusinessStatisticsVO yesterdayRecipelTotal = asRecipelCountMapper.getYesterdayRecipelTotal();
        if (yesterdayRecipelTotal == null) {
            statisticsVO.setYesterdayAddRecipel(0);
            statisticsVO.setYesterdayAddOrder(0);
            statisticsVO.setYesterdayAddOrderPrice(0);
        } else {
            statisticsVO.setYesterdayAddRecipel(yesterdayRecipelTotal.getYesterdayAddRecipel());
            statisticsVO.setYesterdayAddOrder(yesterdayRecipelTotal.getYesterdayAddOrder());
            statisticsVO.setYesterdayAddOrderPrice(yesterdayRecipelTotal.getYesterdayAddOrderPrice());
        }
        BusinessStatisticsVO yesterdayInviteTotal = asRecipelCountMapper.getYesterdayInviteTotal();
        if (yesterdayInviteTotal == null) {
            statisticsVO.setYesterdayAddInvite(0);
        } else {
            statisticsVO.setYesterdayAddInvite(yesterdayInviteTotal.getYesterdayAddInvite());
        }
        return statisticsVO;
    }

    @Override
    public PageVO<AreaStatisticsVO> areaList(PageParamsVO pageParamsVO) {
        PageVO<AreaItemVO> areaItemVOPageVO =
            agentAreaService.queryPage(pageParamsVO, new AreaPagePO(), AgAgentArea.AREA_LEV_REGION);
        List<AreaItemVO> list = areaItemVOPageVO.getList();
        long totalCount = areaItemVOPageVO.getTotalCount();
        int pageSize = (int)areaItemVOPageVO.getPageSize();
        int currPage = (int)areaItemVOPageVO.getCurrPage();
        if (CollUtil.isEmpty(list)) {
            return PageVO.toPageVo(Collections.emptyList(), totalCount, pageSize, currPage);
        }
        Set<Long> idSet = list.stream().map(AreaItemVO::getId).collect(Collectors.toSet());
        List<AreaStatisticsVO> areaStatistics = asRecipelCountMapper.getAreaStatistics(idSet);
        Map<Long, AreaStatisticsVO> recipelMap =
            areaStatistics.stream().collect(Collectors.toMap(AreaStatisticsVO::getId, a -> a, (o, n) -> o));
        return PageVO.toPageVo(list.stream().map(a -> {
            AreaStatisticsVO statistics = new AreaStatisticsVO();
            statistics.setId(a.getId());
            statistics.setAreaName(a.getAreaName());
            statistics.setAreaLeader(a.getAgentName());
            statistics.setLeaderPhone(a.getAgentPhone());
            statistics.setChildCity(a.getChildCity().stream().map(IdAndName::getName).collect(Collectors.joining("/")));
            AreaStatisticsVO recipel = recipelMap.get(a.getId());
            if (recipel == null) {
                statistics.setRecipelTotal(0);
                statistics.setOrderPriceTotal(0);
                statistics.setAreaTotalNumber(0);
                statistics.setChildDoctorTotal(0);
            } else {
                statistics.setRecipelTotal(recipel.getRecipelTotal() == null ? 0 : recipel.getRecipelTotal());
                statistics.setOrderPriceTotal(recipel.getOrderPriceTotal() == null ? 0 : recipel.getOrderPriceTotal());
                statistics.setAreaTotalNumber(recipel.getAreaTotalNumber() == null ? 0 : recipel.getAreaTotalNumber());
                statistics
                    .setChildDoctorTotal(recipel.getChildDoctorTotal() == null ? 0 : recipel.getChildDoctorTotal());
            }
            return statistics;
        }).collect(Collectors.toList()), totalCount, pageSize, currPage);
    }

    @Override
    public AreaStatisticsDetailVO detail(Long areaId) {
        AreaStatisticsDetailVO detail = agAreaMapper.getAreaStatisticsDetail(areaId);
        List<AreaStatisticsDetailVO> areaStatisticsList = agAreaMapper.getAreaStatisticsList(detail.getId());

        List<ChildCityListVO> childCityListVOS = areaStatisticsList.stream().map(a -> {
            ChildCityListVO childCityListVO = new ChildCityListVO();
            childCityListVO.setId(a.getId());
            childCityListVO.setName(a.getAreaName());
            childCityListVO.setLeader(a.getLeaderName());
            childCityListVO.setCardNo(a.getCardNo());
            childCityListVO.setLeaderPhone(a.getLeaderPhone());
            return childCityListVO;
        }).collect(Collectors.toList());
        detail.setChildCityList(childCityListVOS);
        return detail;
    }

    @Override
    public PageVO<AreaStatisticsReportVO> list(PageParamsVO pageParamsVO, Long areaId, Integer type, Integer reportType,
        String reportDate) {
        AreaStatisticsDetailVO detail = detail(areaId);
        Page<AreaStatisticsReportVO> page;
        if (type == 1) {
            page = asAreaCountMapper.getPage(pageParamsVO.getPage(), areaId, ReportUtil.getTypeFormat(reportType),
                ReportUtil.getDateFormat(reportType), reportDate);
        } else {
            page = asAreaCountMapper.getPageProvice(pageParamsVO.getPage(), areaId,
                ReportUtil.getTypeFormat(reportType), ReportUtil.getDateFormat(reportType), reportDate);
        }
        List<AreaStatisticsReportVO> list = page.getRecords();
        long totalCount = page.getTotal();
        int pageSize = (int)page.getSize();
        int currPage = (int)page.getCurrent();
        if (CollUtil.isEmpty(list)) {
            return PageVO.toPageVo(Collections.emptyList(), totalCount, pageSize, currPage);
        }
        list = list.stream().map(a -> {
            a.setAreaName(detail.getAreaName());
            a.setChildCity(
                detail.getChildCityList().stream().map(ChildCityListVO::getName).collect(Collectors.joining("/")));
            a.setLeaderName(detail.getLeaderName());
            a.setLeaderPhone(detail.getLeaderPhone());
            return a;
        }).collect(Collectors.toList());
        return PageVO.toPageVo(list, totalCount, pageSize, currPage);
    }

    @Override
    public byte[] export(String areaIds, Integer type, Integer reportType, String reportDates)
        throws IOException {
        List<AreaExcelVO> list = new ArrayList<>();
        String areaId = "";
        if (StrUtil.isAllNotBlank(areaIds, reportDates)) {
            String[] areaIdArr = areaIds.split(",");
            areaId = areaIdArr[0];
            List<String> areaIdList = Arrays.asList(areaIdArr);
            String[] reportDateArr = reportDates.split(",");
            List<String> reportDateList = Arrays.asList(reportDateArr);
            List<AreaVO> areaList;
            if (type == 1) {
                areaList =
                    asAreaCountMapper.exportArea(areaIdList, ReportUtil.getTypeFormat(reportType), reportDateList);
            } else {
                areaList =
                    asAreaCountMapper.exportProvice(areaIdList, ReportUtil.getTypeFormat(reportType), reportDateList);
            }
            Map<String, List<AreaVO>> map = areaList.stream()
                .collect(Collectors.groupingBy(a -> ReportUtil.getSubReportDate(reportType, a.getReportDate())));

            AreaExcelVO excel;
            for (Map.Entry<String, List<AreaVO>> m : map.entrySet()) {
                List<AreaVO> value = m.getValue();
                excel = new AreaExcelVO();
                excel.setReportDate(m.getKey());
                excel.setAgentTotal(value.stream().mapToInt(AreaVO::getAgentTotal).sum());
                excel.setRecipelTotal(value.stream().mapToInt(AreaVO::getRecipelTotal).sum());
                excel.setOrderPriceTotal(
                    ReportUtil.changeF2Y((int)value.stream().mapToLong(AreaVO::getOrderPriceTotal).sum()));
                list.add(excel);
                if (reportType != 3) {
                    for (AreaVO area : value) {
                        excel = new AreaExcelVO();
                        excel.setReportDate(area.getReportDate());
                        excel.setAgentTotal(area.getAgentTotal());
                        excel.setRecipelTotal(area.getRecipelTotal());
                        excel.setOrderPriceTotal(ReportUtil.changeF2Y(area.getOrderPriceTotal().intValue()));
                        list.add(excel);
                    }
                }
            }
        }
        ExportParams exportParams = new ExportParams();
        exportParams.setTitle("(ID:" + areaId + ") 数据报告");
        ByteArrayOutputStream byteArrayOutputStream;
        try (Workbook workbook = ExcelExportUtil.exportExcel(exportParams, AreaExcelVO.class, list)) {
            byteArrayOutputStream = new ByteArrayOutputStream();
            workbook.write(byteArrayOutputStream);
        }
        return byteArrayOutputStream.toByteArray();
    }

    private QueryWrapper<AreaPagePO> buildEntityWrapper(PageParamsVO pageParamsVO, AreaPagePO pagePO) {
        QueryWrapper<AreaPagePO> entityWrapper = pageParamsVO.getEntityWrapper("t");
        entityWrapper.eq("t.area.area_lev", AgAgentArea.AREA_LEV_REGION);
        return entityWrapper;
    }
}
